package uk.ac.lkl.lpp.xml;



import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import uk.ac.lkl.lpp.PedagogyPlan;


public abstract class XMLConstructor {

    public XMLConstructor() {
        // empty ctor. Necessary for reflection. Explicit here for
        // documentation purposes.
    }


    /**
     * Read the attributes from XML.
     * 
     */
    public Object createFromXML(PedagogyPlan plan, Element element)
            throws XMLException {
        ParameterMap parameterMap = new ParameterMap();
        getParameters(element, parameterMap);
        return createFromParameterMap(plan, parameterMap);
    }


    private void getParameters(Element parent, ParameterMap parameterMap) {
        NodeList parameterElements = parent.getElementsByTagName("Parameter");
        int numElements = parameterElements.getLength();

        for (int i = 0; i < numElements; i++) {
            Element parameterElement = (Element) parameterElements.item(i);
            String name = parameterElement.getAttribute("name");
            String type = parameterElement.getAttribute("type");
            if (type.equals("map")) {
                setMapParameter(name, parameterElement, parameterMap);
            }
            else {
                String value = parameterElement.getAttribute("value");
                parameterMap.setParameter(name, value);
            }
        }
    }


    private void setMapParameter(String parameterName,
                                 Element parentElement,
                                 ParameterMap parameterMap) {
        NodeList childElements = parentElement.getElementsByTagName("MapEntry");
        int numElements = childElements.getLength();

        for (int i = 0; i < numElements; i++) {
            Element childElement = (Element) childElements.item(i);
            String key = childElement.getAttribute("key");
            String value = childElement.getAttribute("value");
            parameterMap.setMapParameter(parameterName, key, value);
        }
    }


    protected abstract Object createFromParameterMap(PedagogyPlan plan,
                                                     ParameterMap parameterMap)
            throws XMLException;


    /**
     * Write the attributes to the file.
     * 
     * Asymmetry: here getting the attributes is abstract and writing them out
     * is general (i.e. base-class functionality). For readAttributesFromXML,
     * getting the attributes is general and creating the in-memory equivalent
     * is abstract.
     * 
     */
    public void convertToXML(PedagogyPlan plan, Element element) {
        ParameterMap parameterMap = new ParameterMap();
        getParametersFromData(plan, parameterMap);
        synchroniseXML(plan, parameterMap);
    }


    protected abstract void getParametersFromData(PedagogyPlan plan,
                                                  ParameterMap parameterMap);


    private void synchroniseXML(PedagogyPlan plan, ParameterMap parameterMap) {
        // todo: write out (to an element?) all the XML depending on
        // the parameter map attributes
    }
}
